/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.inspur.edp.metadata.rtcustomization.api;

import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.Metadata4Ref;
import com.inspur.edp.lcm.metadata.api.entity.MetadataHeader;
import com.inspur.edp.lcm.metadata.api.entity.ProcessMode;
import com.inspur.edp.lcm.metadata.api.entity.uri.AbstractURI;
import com.inspur.edp.lcm.metadata.api.entity.uri.MetadataURI;
import com.inspur.edp.metadata.rtcustomization.api.entity.*;

import java.util.List;

/**
 * 元数据{@link GspMetadata}设计时增删改查接口。
 *
 * <p>供外部调用。是rpc客户端接口，支持拆su环境使用。主要为运行时定制使用。</p>
 *
 * <p>这个类包含了获取设计时元数据实体的接口，包括国际化和非国际化，包括各种类型在设计的元数据。还包含了获取设计时元数据列表的接口。</p>
 *
 * @author liangff
 * @author zhaoleitr
 * @author Lee
 * @author sun
 * @author liubin
 * @version 0.1.24
 */
public interface CustomizationService {
    /**
     * 设计时根据元数据id获取元数据
     *
     * <p>根据元数据uuid，从缓存中获取元数据实体。如果缓存中不存在，则调用rpc服务去rpc服务端获取元数据实体，rpc服务端将从缓存或者数据库中获取元数据实体。
     * 从数据库中获取元数据时，会先从gspmdrtcontent表中查找包中的元数据，然后从gspmdcustomcontent表中查找元数据，最后在gspmdcontent表中查找运行时定制的元数据。
     * Deprecated As of metadata-rtcustomization-api version 0.1.28, replaced by CustomizationService#getGspMetadata(com.inspur.edp.metadata.rtcustomization.api.entity.MetadataQueryParam).</p>
     *
     * @param metadataId 元数据id
     * @return 元数据实体
     */
    @Deprecated
    GspMetadata getMetadata(String metadataId);

    /**
     * 设计时根据元数据id和是否国际化获取元数据实体。
     *
     * <p>需要传递元数据uuid和是否国际化。如果{@code isI18n == true}，则调用{@code getMetadata(String metadataId)}。
     * 否则从缓存中获取非国际化元数据，或者从rpc服务端获取元数据字符串，然后反序列化为元数据实体。
     * Deprecated As of metadata-rtcustomization-api version 0.1.28, replaced by CustomizationService#getGspMetadata(com.inspur.edp.metadata.rtcustomization.api.entity.MetadataQueryParam).</p>
     *
     * @param metadataId 元数据id
     * @param isI18n     是否国际化
     * @return 元数据实体
     */
    @Deprecated
    GspMetadata getMetadata(String metadataId, boolean isI18n);

    /**
     * 根据维度获取已经扩展的元数据（根据被扩展元数据、两个纬度值获取扩展元数据）
     *
     * @param basicMetadataId     基础元数据ID
     * @param basicMetadataCertId 基础元数据证书id
     * @param firstDimension      第一维度值
     * @param secondDimension     第二维度值
     * @return 扩展的元数据
     */
    GspMetadata getMetadataWithDimensions(String basicMetadataId, String basicMetadataCertId, String firstDimension,
                                          String secondDimension);

    /**
     * 根据维度获取已经扩展的元数据（根据基础元数据、两个纬度值获取扩展元数据）
     *
     * @param rootMetadataId      基础元数据ID
     * @param basicMetadataCertId 基础元数据证书id
     * @param firstDimension      第一维度值
     * @param secondDimension     第二维度值
     * @return 扩展的元数据
     */
    GspMetadata getMetadataWithRootMdIdAndDimensions(String rootMetadataId, String basicMetadataCertId, String firstDimension,
                                                     String secondDimension);

    /**
     * 保存扩展维度上的元数据
     *
     * @param dimExtEntity 根据维度扩展的元数据信息实体
     * @return 是否保存成功
     */
    boolean saveExtMetadataWithDimensions(DimensionExtendEntity dimExtEntity);


    /**
     * 删除运行时生成的元数据
     *
     * <p>根据传入的元数据uuid删除运行时生成的元数据。将在rpc服务端删除gspmdcustomcontent表中的元数据，并清除此元数据的所有相关缓存。</p>
     *
     * @param metadataId 元数据ID
     */
    void deleteGeneratedMetadata(String metadataId);

    /**
     * 删除扩展的元数据
     *
     * <p>根据传入的元数据uuid删除运行时定制的元数据。将在rpc服务端删除gspmdcontent表中的元数据，并清除此元数据的所有相关缓存。</p>
     *
     * @param metadataId 元数据id
     * @param certId     证书标识
     */
    void deleteExtMetadata(String metadataId, String certId);

    /**
     * 判断某维度值下，是否已经存在扩展的元数据
     *
     * @param basicMetadataId     基础元数据id
     * @param basicMetadataCertId 基础元数据证书id
     * @param firstDimension      第一维度值
     * @param secondDimension     第二维度值
     * @return 如果存在元数据，返回true,否则返回false
     */
    boolean isExistExtendObjectWithDims(String basicMetadataId, String basicMetadataCertId, String firstDimension, String secondDimension);

    /**
     * 获取所有定制的元数据信息，包括运行时新建的元数据
     * <p>
     * Deprecated As of metadata-rtcustomization-api version 0.1.28, replaced by CustomizationService#getMetadataList(com.inspur.edp.metadata.rtcustomization.api.entity.Metadata4RefQueryParam).
     *
     * @return 元数据信息列表
     */
    @Deprecated
    List<Metadata4Ref> getAllCustomizedMetadataInfo();

    /**
     * 获取所有生成的元数据信息，包括运行时新建的元数据
     * <p>
     * Deprecated As of metadata-rtcustomization-api version 0.1.28, replaced by CustomizationService#getMetadataList(com.inspur.edp.metadata.rtcustomization.api.entity.Metadata4RefQueryParam).
     *
     * @return 元数据信息列表
     */
    @Deprecated
    List<Metadata4Ref> getAllGeneratedMetadataInfo();

    /**
     * 获取指定类型的运行时定制元数据
     * <p>
     * Deprecated As of metadata-rtcustomization-api version 0.1.28, replaced by CustomizationService#getMetadataList(com.inspur.edp.metadata.rtcustomization.api.entity.Metadata4RefQueryParam).
     *
     * @param metadataTypes 元数据类型列表
     * @return 元数据信息列表
     */
    @Deprecated
    List<Metadata4Ref> getAllCustomizedMetadataInfo(List<String> metadataTypes);

    /**
     * 获取指定类型的运行时定制元数据
     * <p>
     * Deprecated As of metadata-rtcustomization-api version 0.1.28, replaced by CustomizationService#getMetadataList(com.inspur.edp.metadata.rtcustomization.api.entity.Metadata4RefQueryParam).
     *
     * @param metadataTypes 元数据类型列表
     * @return 元数据信息列表
     */
    @Deprecated
    List<Metadata4Ref> getAllGeneratedMdInfoWithTypes(List<String> metadataTypes);

    /**
     * 根据基础元数据递归获取该元数据下所有扩展的元数据及扩展关系
     *
     * @param basicMetadataID     基础元数据ID
     * @param basicMetadataCertId 基础元数据证书ID
     * @return 元数据扩展信息及扩展元数据信息实体列表
     */
    List<DimensionExtendEntity> getMetadataInfoRecusively(String basicMetadataID, String basicMetadataCertId);

    /**
     * 将元数据从设计表中发布到运行表
     *
     * <p>根据元数据uuid和certId发布元数据。rpc服务端将会从gspmdcontent表中获取元数据，保存到gspmdcontent表中，并更新运行时缓存。</p>
     *
     * @param metadataId 元数据ID
     * @param certId     证书id
     * @return 发布成功，返回true，发布失败，返回false
     **/
    boolean releaseMetadataToRt(String metadataId, String certId);

    /**
     * 根据扩展元数据标识，获取扩展关系
     *
     * @param metadataId 元数据ID
     * @param certId     元数据证书ID
     * @return 维度扩展关系
     */
    DimensionExtendRelation getDimExtRelationByExtMetadata(String metadataId, String certId);

    /**
     * 根据扩展元数据获取基础元数据,此基础元数据为 根元数据
     * be现在解析元数据，但是考虑产品元数据承载大部分逻辑，扩展内容是少量内容；
     * 还要获取基础元数据，通过基础元数据解析具体的代码逻辑，进行扩展内容合并执行
     *
     * @param metadataId 元数据id
     * @param certId     证书id
     * @return 元数据实体
     */
    GspMetadata getBasicMetadataByExtMdId(String metadataId, String certId);


    /**
     * 根据扩展元数据获取基础元数据,此基础元数据为 根元数据
     *
     * @param metadataId 元数据id
     * @param certId     证书id
     * @return 元数据信息
     */
    Metadata4Ref getBasicPkgMetadataByExtMdId(String metadataId, String certId);

    /**
     * 根据扩展元数据获取被扩展的元数据
     *
     * @param metadataId 元数据id
     * @param certId     证书id
     * @return 元数据实体
     */
    GspMetadata getParentMdByExtMdId(String metadataId, String certId);

    /**
     * 根据扩展元数据获取被扩展的元数据
     *
     * @param metadataId 元数据id
     * @param certId     证书id
     * @return 元数据实体
     */
    List<DimensionExtendEntity> getExtMdByBasicMdId(String metadataId, String certId);

    /**
     * 根据元数据ID跟版本获取当前关联的增量
     *
     * @param metadataId 元数据id
     * @param certId     证书id
     * @param version    版本
     * @return 运行时定制增量
     */
    AbstractCustomizedContent getChangeset(String metadataId, String certId, String version);


    /**
     * 运行时动态保存元数据
     *
     * <p>将传过来的元数据实体保存到gspmdcustomcontent表中，保存前会检查gspmdcustomcontent、gspmdcontent、gspmdrtcontent表中是否含有相同namespace、code、type的元数据。
     * 保存成功后会清除所有相关缓存。</p>
     *
     * @param metadata 元数据实体
     */
    void save(GspMetadata metadata);

    /**
     * 保存与检查元数据
     *
     * @param metadata 元数据实体
     */
    void saveCheck(GspMetadata metadata);

    /**
     * 获取特定类型的元数据列表
     *
     * <p>获取元数据列表，可以传入多个元数据类型，用,隔开。也可以传null，传null则获取所有元数据列表。在rpc服务端调用{@code getMetadataListByFilter(MetadataFilter metadataFilter)}方法。
     * 获取的元数据列表包括包gspmdrtcontent表中sourcetype为1的元数据，gspmdcustomcontent表中的元数据、gspmdcontent表中的元数据。</p>
     * <p>
     * Deprecated As of metadata-rtcustomization-api version 0.1.28, replaced by CustomizationService#getMetadataList(com.inspur.edp.metadata.rtcustomization.api.entity.Metadata4RefQueryParam).
     *
     * @param metadataTypes 元数据类型列表
     * @return 元数据信息列表
     */
    @Deprecated
    List<Metadata4Ref> getMetadataList(String metadataTypes);

    /**
     * 获取特定类型的元数据列表，可以区分是否解析型
     *
     * <p>获取元数据列表，需传入元数据类型和是否解析型。元数据类型可以传入多个元数据类型，用,隔开。也可以传null，传null则获取所有元数据列表。
     * 在rpc服务端调用{@code getMetadataListByFilter(MetadataFilter metadataFilter)}方法。
     * 获取的元数据列表包括包gspmdrtcontent表中sourcetype为1的元数据，gspmdcustomcontent表中的元数据、gspmdcontent表中的元数据。</p>
     * <p>
     * Deprecated As of metadata-rtcustomization-api version 0.1.28, replaced by CustomizationService#getMetadataList(com.inspur.edp.metadata.rtcustomization.api.entity.Metadata4RefQueryParam).
     *
     * @param metadataTypes    元数据类型列表
     * @param isInterpretation 是否解析型
     * @return 元数据信息列表
     */
    @Deprecated
    List<Metadata4Ref> getMetadataList(String metadataTypes, Boolean isInterpretation);

    /**
     * 获取特定类型的元数据列表，可以根据processMode进行过滤
     *
     * <p>获取元数据列表，需传入元数据类型和processmode类型。元数据类型可以传入多个元数据类型，用,隔开。也可以传null，传null则获取所有元数据列表。
     * 在rpc服务端调用{@code getMetadataListByFilter(MetadataFilter metadataFilter)}方法。
     * 获取的元数据列表包括包gspmdrtcontent表中sourcetype为1的元数据，gspmdcustomcontent表中的元数据、gspmdcontent表中的元数据。</p>
     * <p>
     * Deprecated As of metadata-rtcustomization-api version 0.1.28, replaced by CustomizationService#getMetadataList(com.inspur.edp.metadata.rtcustomization.api.entity.Metadata4RefQueryParam).
     *
     * @param metadataTypes 元数据类型列表
     * @param processMode   处理模式
     * @return 元数据信息列表
     */
    @Deprecated
    List<Metadata4Ref> getMetadataList(String metadataTypes, ProcessMode processMode);

    /**
     * 获取全部元数据列表
     * <p>
     * Deprecated As of metadata-rtcustomization-api version 0.1.28, replaced by CustomizationService#getMetadataList(com.inspur.edp.metadata.rtcustomization.api.entity.Metadata4RefQueryParam).
     *
     * @return 元数据信息列表
     */
    @Deprecated
    List<Metadata4Ref> getMetadataList();

    /**
     * 根据特定条件获取元数据
     *
     * <p>可以根据namespace、code、typeCode获取元数据实体。这三个标识可以确定唯一的元数据。仅可以获取gspmdrtcontent表中sourcetype为1的元数据。</p>
     *
     * @param nameSpace 命名空间
     * @param code      编号
     * @param typeCode  元数据类型编号
     * @return 元数据实体
     */
    GspMetadata getMetadataBySemanticId(String nameSpace, String code, String typeCode);

    /**
     * 判断元数据能否删除
     *
     * @param metadataId 元数据id
     * @param certId     证书id
     * @return 如果元数据可以删除，返回true，否则返回false
     */
    boolean isMdDeletable(String metadataId, String certId);

    /**
     * 根据元数据uuid列表删除其缓存
     *
     * <p>删除缓存需要传递元数据uuid列表。删除缓存时会遍历uuid列表，然后遍历国际化语言表删除各个国际化的缓存，也删除非国际化的缓存。同时删除运行时的缓存。</p>
     *
     * @param metadataIds 待删除的元数据编码集合
     * @author sunhongfei01
     * @since 2021-7-20
     */
    void removeCacheByMetadataIds(List<String> metadataIds);

    /**
     * 根据产品元数据id与维度值动态获取存在的扩展元数据（根据父元数据、两个纬度值获取扩展元数据）
     * 如果不存在相应维度值的扩展，根据扩展关系获取基础维度的扩展元数据，直至获取对应的产品元数据
     *
     * @param rootMetadataId       根元数据ID
     * @param rootMetadataCertId   根元数据证书id
     * @param firstDimensionValue  第一维度值
     * @param secondDimensionValue 第二维度值
     * @return 扩展的元数据
     */
    GspMetadata getDynamicMetadataWithRootMdIDAndDimensions(String rootMetadataId, String rootMetadataCertId,
                                                            String firstDimensionValue, String secondDimensionValue);

    /**
     * 根据元数据id、是否国际化、设计时or运行时参数查询元数据实体。
     *
     * <p>先从redis缓存查找，查找不到则通过rpc服务端获取元数据。</p>
     *
     * @param metadataQueryParam 元数据查询对象
     * @return 元数据实体
     */
    GspMetadata getGspMetadata(MetadataQueryParam metadataQueryParam);

    GspMetadata getGspMetadata(MetadataURIQueryParam metadataURIQueryParam);

    /**
     * 获取特定类型的元数据列表，可以根据条件过滤
     *
     * <p>支持查询gspmdcustomcontent、Gspmdcontent、gspmdrtcontent的数据，并可根据metadataType、processMode进行过滤
     *
     * @param metadata4RefQueryParam 查询参数
     * @return 元数据信息列表
     */
    List<Metadata4Ref> getMetadataList(Metadata4RefQueryParam metadata4RefQueryParam);

    /**
     * 更新扩展关系
     * 使用场景：更新扩展关系中的维度值
     * 使用方式：更新指定的扩展关系维度值，需要构造（extMdId，extMdCode，extMdNamespace, extMdType, firstDimCode，firstDimValue,secDimCode,secDimValue)
     * extMdId唯一确定扩展关系，(extMdCode, exMdNamespace, exMdType)用于出异常时提示
     * (firstDimCode,firstDimValue,secDimCode,secDimValue)指定要更新的维度值，如果某个维度没有值，不需要构造，传空。
     * firstDimCode，secDimCode用于标识维度信息，建议构造。可以不构造，传空，会使用原关系中维度编号替换空值。
     */
    void updateExtRelation(DimensionExtendRelation extendRelation);

    MetadataURI getRefMetadataURI(String metadataId);

    /**
     * 根据id获取元数据引用(不带content)
     *
     * @param metadataId
     * @return
     */
    Metadata4Ref getMetadata4RefById(String metadataId);
}
